<script setup lang="ts">
import type { DescriptionsProps } from '#/components/spark-descriptions/types';
import type { SparkTypes } from '#/utils/types/types';

import { ref } from 'vue';

import { useVbenModal } from '@vben/common-ui';

import { SparkFilesPreview, SparkHtml } from '#/components';
import { SparkImagePreview } from '#/components/spark-image-preview';
import { useDictionaries } from '#/utils';

const props = withDefaults(defineProps<DescriptionsProps>(), {
  title: '',
  size: 'middle',
  bordered: true,
  layout: 'horizontal',
  column: { xs: 1, sm: 2, md: 3 },
  api: undefined,
  params: () => ({}),
});

const dictCodes = ref<string[]>([]);
const { translateText } = useDictionaries(dictCodes);

const data = ref<Record<string, any>>({});
const showItemColumns = ref<Array<SparkTypes.DetailsTypes>>([]);

async function fetchApi(paramsOverride?: Record<string, any>) {
  const { api, params } = props;
  if (!api) {
    return;
  }
  try {
    const combinedParams = { ...params, ...paramsOverride };
    data.value = await api(combinedParams);
  } catch (error) {
    console.warn(error);
  }
}

const [Modal, modalApi] = useVbenModal({
  title: '详情',
  showConfirmButton: false,
  cancelText: '关闭',
});

/**
 * 打开详情
 * @param params 接口参数
 * @param columns 列配置 - 需要保证包含字段名：title[标题字段] field[取值字段]
 */
function open(
  params?: Record<string, any>,
  columns: Array<SparkTypes.DetailsTypes>,
) {
  // 提取所有 dictCode 并过滤无效值
  dictCodes.value = columns
    // 提取字段
    .map((c) => c.params?.dictCode)
    // 过滤空值并类型断言
    .filter((code): code is string => !!code)
    // 去重
    .filter((v, i, arr) => arr.indexOf(v) === i);

  fetchApi(params);
  sort(columns);
  if (props?.title) {
    modalApi.setState({ title: props?.title });
  }
  modalApi.open();
}

// 对数据进行排序赋值
function sort(columns: Array<SparkTypes.DetailsTypes>) {
  // 对 columns 按照 sort 属性进行升序排序
  // 将排序后的列赋值给 showItemColumns.value
  showItemColumns.value = [...columns].sort((a, b) => {
    // 如果 sort 不存在，默认设置为 Infinity
    const sortA = a.sort ?? Infinity;
    const sortB = b.sort ?? Infinity;
    return sortA - sortB;
  });
}

defineExpose({ open });
</script>
<template>
  <Modal>
    <a-descriptions
      :bordered="props?.bordered"
      :size="props?.size"
      :layout="props?.layout"
      :column="props?.column"
    >
      <a-descriptions-item
        v-for="(item, index) in showItemColumns"
        :key="index"
        :label="item?.title"
        :span="item?.span"
      >
        <template v-if="item?.params?.dictCode">
          <component
            :is="() => translateText(data[item?.field], item?.params?.dictCode)"
          />
        </template>
        <template v-else-if="item?.params?.html">
          <SparkHtml :content="data[item?.field]" btn-type="primary" />
        </template>
        <template v-else-if="item?.params?.image">
          <SparkImagePreview
            :image-urls="data[item?.field]"
            :preview-width="60"
            :preview-height="60"
          />
        </template>
        <template v-else-if="item?.params?.files">
          <SparkFilesPreview :urls="data[item?.field]" />
        </template>
        <template v-else>
          {{ data[item?.field] }}
        </template>
      </a-descriptions-item>
    </a-descriptions>
  </Modal>
</template>
